package philbot;

import java.util.Random;

/**
 * This class is used to represent a single bot
 * @author philip
 */
public class BotHolder {
	private final PhilBotCore.SearchAlg alg;
	private final PhilBotCore.SearchMode mode;
	private PhilBotCore core;
	private final int depth;
	private final int count;
	private final int asWindow;
	private final boolean isRandom;
	private Random rand = null;
	private final Evaluator eval;
	//private int window;
	/**
	 * Use this class with the builder pattern to construct a botholder
	 */
	public static class Builder{
		private PhilBotCore.SearchAlg alg;
		private PhilBotCore.SearchMode mode;
		private int depth;
		private int count;
		private int asWindow;
		private boolean isRandom;
		private Evaluator eval;
		public Builder(){
			this.alg = PhilBotCore.SearchAlg.MEMORYAB;
			this.mode = PhilBotCore.SearchMode.SIMPLE;
			this.depth = 3;
			this.asWindow = Integer.MAX_VALUE;
			this.count = Integer.MAX_VALUE;
			this.isRandom = false;
			this.eval = Evaluator.defaultEvaluator();
		}
		public Builder depth(int d){
			this.depth = d;
			return this;
		}
		public Builder count(int c){
			this.count = c;
			return this;
		}
		public Builder alg(PhilBotCore.SearchAlg a){
			this.alg = a;
			return this;
		}
		public Builder mode(PhilBotCore.SearchMode m){
			this.mode = m;
			return this;
		}
		public Builder random(boolean isRandom){
			this.isRandom = isRandom;
			return this;
		}
		public BotHolder build(){
			return new BotHolder(this);
		}
	}
	
	private BotHolder(Builder b){
		this.alg = b.alg;
		this.mode = b.mode;
		this.count = b.count;
		this.depth = b.depth;
		this.asWindow = b.asWindow;
		this.isRandom = b.isRandom;
		TransTable t = new TransTable();
		this.core = new PhilBotCore(t);
		this.eval = b.eval;
	}
	
	public void clearTables(){
		TransTable t = new TransTable();
		this.core = new PhilBotCore(t);
	}
	
	public AbstractPosition play(AbstractPosition a){
		if(isRandom){
			if(rand == null)
				rand = new Random(System.nanoTime());
			int length = a.getChildren().size();
			if(length < 2)
				return a.getChildren().get(0);
			return a.getChildren().get(rand.nextInt(length - 1));
		}
		int i = core.search(mode, alg, a, count, depth, asWindow, eval);
		AbstractPosition v = core.pvtable.getPV(a);
		if(v == null){
			System.out.println("null!!! at " + i);
		}
		return v;
	}
	
	public int getNodeCunt(){
		return core.nodeCount;
	}

	@Override public String toString(){
		StringBuilder b = new StringBuilder("BOT: ");
		b.append(mode).append(" ").append(alg).append(" at depth:  ");
		if(depth == Integer.MAX_VALUE){
			b.append("MAX VALUE");
		}else{
			b.append(depth);
		}
		b.append(" and limited to: ");
		if(count == Integer.MAX_VALUE){
			b.append("MAX VALUE");
		}else{
			b.append(depth);
		}
		return b.toString();
	}
}
